﻿using Leo.Common.MQ;
using System.Reflection;

namespace Leo.Common.RabbitMQ
{
   
    public static class RabbitObjectScanner
    { 
        public static List<RabbitObjectBase> ScanAppDomainForQueueDeclare(params string[] ignoreAsseblyNamePrefix)
        {
            RabbitObjectScanner.<> c__DisplayClass0_0 CS$<> 8__locals1 = new RabbitObjectScanner.<> c__DisplayClass0_0();
            RabbitObjectScanner.<> c__DisplayClass0_0 CS$<> 8__locals2 = CS$<> 8__locals1;
            List<string> list = new List<string>();
            list.Add("Microsoft.");
            list.Add("System.");
            list.Add("log4net");
            list.Add("Newtonsoft.Json");
            list.Add("Swashbuckle.");
            list.Add("netstandard");
            list.Add("RabbitMQ.Client");
            list.Add("SqlSugarCore");
            list.Add("FreeRedis");
            list.Add("Confluent.Kafka");
            list.Add("BouncyCastle.");
            list.Add("MediatR.");
            list.Add("KubeClient");
            list.Add("MongoDB.");
            list.Add("SkiaSharp");
            list.Add("NPOI");
            list.Add("Aliyun.");
            list.Add("aliyun-");
            list.Add("RulesEngine");
            list.Add("Alipay.");
            list.Add("Baidu.");
            list.Add("EmitMapper.");
            list.Add("Foundatio");
            list.Add("Pinyin4Net-");
            list.Add("ThoughtWorks.");
            list.Add("QRCoder");
            list.Add("AutoMapper");
            list.Add("Jareds.Common");
            CS$<> 8__locals2.knownIgnoreAssemblyNamePrefixes = list;
            if (ignoreAsseblyNamePrefix != null && ignoreAsseblyNamePrefix.Length != 0)
            {
                CS$<> 8__locals1.knownIgnoreAssemblyNamePrefixes.AddRange(ignoreAsseblyNamePrefix);
            }
            Assembly.GetExecutingAssembly();
            IEnumerable<Type> enumerable = (from asm in AppDomain.CurrentDomain.GetAssemblies()
                                            where !CS$<> 8__locals1.knownIgnoreAssemblyNamePrefixes.Any((string f) => asm.FullName.StartsWith(f))

            select asm).SelectMany((Assembly asm) => asm.GetTypes()).Where(new Func<Type, bool>(RabbitObjectScanner.IsTargetType));
            List<RabbitObjectBase> list2 = new List<RabbitObjectBase>();
            foreach (Type type in enumerable)
            {
                MethodInfo[] array = RabbitObjectScanner.SearchDeclareMethod(type);
                if (array != null && array.Length != 0)
                {
                    MethodInfo[] array2 = array;
                    for (int i = 0; i < array2.Length; i++)
                    {
                        RabbitObjectBase rabbitObjectBase = RabbitObjectScanner.TryExecuteDeclareQueueMethod(array2[i]);
                        if (rabbitObjectBase != null)
                        {
                            list2.Add(rabbitObjectBase);
                        }
                    }
                }
            }
            return list2;
        }

        private static bool IsTargetType(Type type)
        {
            bool flag = type.IsClass && !type.IsAbstract && typeof(IMessageModel).IsAssignableFrom(type);
            bool flag2 = type.IsPublic && type.IsClass && type.IsAbstract && type.IsSealed;
            return flag || flag2;
        }

        //[return: Nullable(new byte[]
        //{
        //    2,
        //    1
        //})]
        private static MethodInfo[] SearchDeclareMethod(Type type)
        {
            MethodInfo[] methods = type.GetMethods(BindingFlags.Static | BindingFlags.Public);
            if (methods == null || methods.Length == 0)
            {
                return null;
            }
            return (from m in methods
                    where RabbitObjectScanner.ReturnTypeIsRabbitObject(m) && RabbitObjectScanner.IfMethodIsParameterless(m)
                    select m).ToArray<MethodInfo>();
        }

        private static bool ReturnTypeIsRabbitObject(MethodInfo m)
        {
            return m.ReturnType == typeof(RabbitQueueInfo) || m.ReturnType == typeof(RabbitExchangeInfo);
        }

        private static bool IfMethodIsParameterless(MethodInfo method)
        {
            ParameterInfo[] parameters = method.GetParameters();
            return parameters == null || parameters.Length == 0;
        }

        //[return: Nullable(2)]
        private static RabbitObjectBase TryExecuteDeclareQueueMethod(MethodInfo method)
        {
            if (method == null)
            {
                return null;
            }
            string str = method.DeclaringType.Name + "." + method.Name + "()";
            RabbitObjectBase result;
            try
            {
                object obj = method.Invoke(null, null);
                if (obj == null)
                {
                    result = null;
                }
                else
                {
                    result = (obj as RabbitObjectBase);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("执行" + str + "方法出现异常，错误信息：" + ex.Message);
                Console.WriteLine(ex.StackTrace);
                result = null;
            }
            return result;
        }
    }
}
